/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.demo.codegen.enume.support;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.google.gson.GsonBuilder;
import com.j256.ormlite.field.DataPersisterManager;
import net.apexes.commons.json.gson.Gsons;
import net.apexes.commons.json.jackson.Jacksons;
import net.apexes.commons.lang.Dates;
import net.apexes.commons.lang.Enume;
import net.apexes.commons.lang.EnumeRegistry;
import net.apexes.commons.ormlite.EnumeByStringType;
import net.apexes.commons.querydsl.support.QuerydslEnumeSupport;
import net.apexes.demo.codegen.entity.enums.GoodsCategory;
import net.apexes.demo.codegen.entity.enums.GoodsType;
import net.apexes.demo.codegen.entity.enums.PayType;
import net.apexes.demo.codegen.entity.enums.StatusFlag;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 */
public class DemoEnumeSupport extends QuerydslEnumeSupport {

    private static class LazySingletonHolder {
        private static final DemoEnumeSupport INSTANCE = new DemoEnumeSupport();
    }

    public static DemoEnumeSupport getInstance() {
        return LazySingletonHolder.INSTANCE;
    }
    
    public static final EnumeRegistry enumeRegistry = new EnumeRegistry(conf -> {
        conf.enume(StatusFlag.class).column("STATUS_FLAG");
        conf.enume(PayType.class).table("PAY").column("PAY_TYPE");
        conf.enume(GoodsType.class).table("GOODS").column("GOODS_TYPE");
        conf.enume(GoodsCategory.class).table("GOODS").column("GOODS_CATEGORY");
    });

    private DemoEnumeSupport() {
        super(enumeRegistry);
    }

    public void registerDataPersisters() {
        for (Class<? extends Enume<?>> enumeClass : this.getEnumeClasses()) {
            @SuppressWarnings("unchecked")
            Class<Enume<String>> classType = (Class<Enume<String>>) enumeClass;
            DataPersisterManager.registerDataPersisters(new EnumeByStringType<>(classType));
        }
    }

    public ObjectMapper createObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.setDateFormat(new SimpleDateFormat(Dates.TIMESTAMP_PATTERN));
        objectMapper.registerModule(Jacksons.createModule(getEnumeClasses()));
        objectMapper.registerModule(new JavaTimeModule());
        return objectMapper;
    }

    public GsonBuilder createGsonBuilder() {
        GsonBuilder gsonBuilder = Gsons.createGsonBuilder(getEnumeClasses());
        return javaTimeSupport(gsonBuilder);
    }

    public static GsonBuilder javaTimeSupport(GsonBuilder gsonBuilder) {
        gsonBuilder.setDateFormat(Dates.TIMESTAMP_PATTERN);
        gsonBuilder.registerTypeAdapter(LocalDate.class, GsonJavaTimeSupport.createLocalDateJsonSerializer());
        gsonBuilder.registerTypeAdapter(LocalDate.class, GsonJavaTimeSupport.createLocalDateJsonDeserializer());
        gsonBuilder.registerTypeAdapter(LocalDateTime.class, GsonJavaTimeSupport.createLocalDateTimeJsonSerializer());
        gsonBuilder.registerTypeAdapter(LocalDateTime.class, GsonJavaTimeSupport.createLocalDateTimeJsonDeserializer());
        return gsonBuilder;
    }

}
